#pragma once 
#include "util.hpp"
#include <mutex>
#include <cassert>
#define INSERT_USER "insert user values(null, '%s',%s, 1000, 0,0);"//注册用户时，插入到数据库
#define SELECT_USER "select * from user where user_name='%s' and password='%s';"//登录验证
#define SELECT_USER_BY_USER_NAME "select * from user where user_name='%s';"//通过用户名查询用户信息
#define SELECT_USER_BY_USER_ID "select * from user where id=%d;"//通过用户id查询用户信息
#define UPDATE_USER_WIN "update user set score=score+30,total_count=total_count+1,win_count=win_count+1 where id=%d;"//赢了更新
#define UPDATE_USER_LOSE "update user set score=score-30,total_count=total_count+1 where id=%d;"//输了更新
class user_table
{
public:
    user_table(const std::string &host, const std::string &user_name,
               const std::string &password, const std::string &db_name,uint16_t port=3306)
    {
        _mysql = mysql_util::mysql_create(host, user_name, password, db_name, port);
        assert(_mysql); // 如果连接数据库失败直接断言出错
    }
    ~user_table()
    {
        mysql_util::mysql_destroy(_mysql);
        _mysql=nullptr;
    }

    //注册--->新增用户
    bool insert(Json::Value&user)
    {

      //解析名字和密码
      if(user["username"].isNull()||user["password"].isNull())
      {
        DBG_LOG("INSERT: PASSWORD OR USERNAME IS NULL\n");//输入密码或者用户名是空的到日志中
        return false;
      }

      //把插入数据库命令放入缓冲区
      char sql_buffer[1024]={0};//开辟缓冲区
      int result=snprintf(sql_buffer,sizeof(sql_buffer),INSERT_USER,user["username"].asCString(),user["password"].asCString());
      if (result<0)
      {
        DBG_LOG("INSERT:SNPRINTF ERROR\n");
        return false;//直接返回错误
      }

      //执行insert命令插入数据库
      bool ret=mysql_util::mysql_exec(_mysql,sql_buffer);
      if(ret==false)
      {
        DBG_LOG("INSERT:MYSQL INSERT ERROR\n");
        return false;
      }

      return true;//执行插入成功，创建出新用户 
    }
    
    //登录验证，并返回详细的用户信息
    bool login(Json::Value&user)
    {
      //检测是否输入了用户名和密码
      if(user["username"].isNull()||user["password"].isNull())
      {
        DBG_LOG("LOGIN: PASSWORD OR USERNAME IS NULL\n");
        return false;
      }

      //使用sql语句select where查询数据库当中是否有对应的用户
      char sql_buffer[1024]={0};
      snprintf(sql_buffer,sizeof(sql_buffer),
      SELECT_USER,user["username"].asCString(),
      user["password"].asCString());
     
      //创建res保存select结果
      MYSQL_RES *res=NULL;
    {
      //保护数据库的访问，加锁
      //RAII管理锁资源
      std::unique_lock<std::mutex> lock(_mutex);
      bool ret=mysql_util::mysql_exec(_mysql,sql_buffer);
      if(ret==false)
      {
        DBG_LOG("LOGIN:USER LOGIN ERROR\n");
        return false;
      }
      
      //由于主键所以有数据就只能有一条，要么没数据
      res=mysql_store_result(_mysql);
      if(res==NULL)
      {
        DBG_LOG("LOGIN:HAVE NO LOGIN USER INFO\n");
        return false;
      }
    }
     //处理返回的详细信息
    int row_num=mysql_num_rows(res);
    if(row_num!=1){
      DBG_LOG("LOGIN:THE USER INFO IS NOT UNIQUE\n");
      mysql_free_result(res);
      return false;
    }
    MYSQL_ROW row=mysql_fetch_row(res);
    
    // 添加错误检查
    try {
        if (row[0]) {
            user["id"] = (Json::UInt64)std::stoull(row[0]);
            DBG_LOG("用户ID: %s", row[0]);
        } else {
            DBG_LOG("用户ID为空");
            mysql_free_result(res);
            return false;
        }
        
        // user["username"]=还是用原来用户的name
        //user["password"]=原来用户的密码
        if (row[3]) {
            user["score"] = (Json::UInt64)std::stoull(row[3]);
            DBG_LOG("用户分数: %s", row[3]);
        } else {
            user["score"] = (Json::UInt64)0;
            DBG_LOG("用户分数为空，设为0");
        }
        
        if (row[4]) {
            user["total_count"] = std::stoi(row[4]);
            DBG_LOG("总场次: %s", row[4]);
        } else {
            user["total_count"] = 0;
            DBG_LOG("总场次为空，设为0");
        }
        
        if (row[5]) {
            user["win_count"] = std::stoi(row[5]);
            DBG_LOG("胜利场次: %s", row[5]);
        } else {
            user["win_count"] = 0;
            DBG_LOG("胜利场次为空，设为0");
        }
    } catch (const std::exception& e) {
        DBG_LOG("数据转换错误: %s", e.what());
        mysql_free_result(res);
        return false;
    }
    
    mysql_free_result(res);
    return true;  
    }

    //通过用户名查询详细的用户信息
    bool get_by_user_name(const std::string &user_name,Json::Value& user)
    {
       char sql_buffer[1024]={0};
       snprintf(sql_buffer,sizeof(sql_buffer),
       SELECT_USER_BY_USER_NAME,user_name.c_str());//创建查询命令

        DBG_LOG("执行SQL: %s", sql_buffer);

      //获取返回结果
       MYSQL_RES *res=NULL;
       {
        //RAII管理锁资源
         std::unique_lock<std::mutex> lock(_mutex);
        bool ret=mysql_util::mysql_exec(_mysql,sql_buffer);//执行sql语句
        if(ret==false){
          DBG_LOG("GET USER BY USER_NAME: SQL ERROR\n");
          return false;
        } 
       
       res=mysql_store_result(_mysql);//拿到数据结果
       if(res==NULL){
         DBG_LOG("GET USER BY USER_NAME:HAVE NO USER INFO \n");
         
         return false;
       }
       }
       int row_num=mysql_num_rows(res);
       if(row_num!=1)
       {
         DBG_LOG("GET USER BY USER_NAME:THE USER INFO IS NOT UNIQUE\n");
           mysql_free_result(res);
         return false;
       }
      MYSQL_ROW row=mysql_fetch_row(res);
       
       try {
           if (row[0]) {
               user["id"]=(Json::UInt64)std::stoull(row[0]);
               DBG_LOG("用户ID: %s", row[0]);
           } else {
               user["id"]=(Json::UInt64)0;
               DBG_LOG("用户ID为空，设为0");
           }
           
           if (row[1]) {
               user["username"]=row[1];
               DBG_LOG("用户名: %s", row[1]);
           } else {
               user["username"]="";
               DBG_LOG("用户名为空");
           }
           
           if (row[3]) {
               user["score"]=(Json::UInt64)std::stoull(row[3]);
               DBG_LOG("分数: %s", row[3]);
           } else {
               user["score"]=(Json::UInt64)0;
               DBG_LOG("分数为空，设为0");
           }
           
           if (row[4]) {
               user["total_count"]=std::stoi(row[4]);
               DBG_LOG("总场次: %s", row[4]);
           } else {
               user["total_count"]=0;
               DBG_LOG("总场次为空，设为0");
           }
           
           if (row[5]) {
               user["win_count"]=std::stoi(row[5]);
               DBG_LOG("胜利场次: %s", row[5]);
           } else {
               user["win_count"]=0;
               DBG_LOG("胜利场次为空，设为0");
           }
       } catch (const std::exception& e) {
           DBG_LOG("数据转换错误: %s", e.what());
           mysql_free_result(res);
           return false;
       }
       
       mysql_free_result(res);
       return true;
    }
    
    //通过用户id查询详细的用户信息
    bool get_by_user_id(uint64_t id,Json::Value&user)
    {
        char sql_buffer[1024]={0};
       snprintf(sql_buffer,sizeof(sql_buffer),
       SELECT_USER_BY_USER_ID,id);//创建查询命令

      //获取返回结果
       MYSQL_RES *res=NULL;
       {
        //RAII管理锁资源
         std::unique_lock<std::mutex> lock(_mutex);
        bool ret=mysql_util::mysql_exec(_mysql,sql_buffer);//执行sql语句
        if(ret==false){
          DBG_LOG("GET USER BY ID: SQL ERROR\n");
          return false;
        } 
       
        res=mysql_store_result(_mysql);//拿到数据结果
        if(res==NULL){
         DBG_LOG("GET USER BY ID:HAVE NO USER INFO \n");
         return false;
        }
       }
       int row_num=mysql_num_rows(res);
       if(row_num!=1)
       {
         DBG_LOG("GET USER BY ID:THE USER INFO IS NOT UNIQUE\n");
          mysql_free_result(res);
         return false;
       }
     MYSQL_ROW row=mysql_fetch_row(res);
       
       try {
           user["id"]=(Json::UInt64)id;
           // 检查用户名是否为空
           if (row[1]) {
               user["username"]=row[1];
               DBG_LOG("用户名: %s", row[1]);
           } else {
               user["username"]="";
               DBG_LOG("用户名为空");
           }
           
           // 检查各个字段是否为空
           if (row[3]) {
               user["score"]=(Json::UInt64)std::stoull(row[3]);
               DBG_LOG("分数: %s", row[3]);
           } else {
               user["score"]=(Json::UInt64)0;
               DBG_LOG("分数为空，设为0");
           }
           
           if (row[4]) {
               user["total_count"]=std::stoi(row[4]);
               DBG_LOG("总场次: %s", row[4]);
           } else {
               user["total_count"]=0;
               DBG_LOG("总场次为空，设为0");
           }
           
           if (row[5]) {
               user["win_count"]=std::stoi(row[5]);
               DBG_LOG("胜利场次: %s", row[5]);
           } else {
               user["win_count"]=0;
               DBG_LOG("胜利场次为空，设为0");
           }
       } catch (const std::exception& e) {
           DBG_LOG("数据转换错误: %s", e.what());
           mysql_free_result(res);
           return false;
       }
       
       mysql_free_result(res);
       return true;
    }

    //用户胜利的时候，天梯分数增加30分，胜利场次增加1次，战斗场次增加1次
    bool win(uint64_t id)
    {
       char sql_buffer[1024]={0};
       snprintf(sql_buffer,sizeof(sql_buffer),
       UPDATE_USER_WIN,id);
       if(!mysql_util::mysql_exec(_mysql,sql_buffer)){
        DBG_LOG("WIN:UPDATE USER WIN INFO ERROR\n");
        return false;
       }
       return true;
    }

    //用户失败的时候，天梯分数减少30分，胜利场次不变，战斗场次增加1次
    bool lose(uint64_t id)
    {
       char sql_buffer[1024]={0};
       snprintf(sql_buffer,sizeof(sql_buffer),
       UPDATE_USER_LOSE,id);
       if(!mysql_util::mysql_exec(_mysql,sql_buffer)){
        DBG_LOG("LOSE:UPDATE USER LOSE INFO ERROR\n");
        return false;
       }
       return true;
    }
private:
    MYSQL *_mysql;     // mysql连接句柄
    std::mutex _mutex; // 互斥锁保护数据库的访问操作
};